﻿using System.Drawing;
using System.Drawing.Imaging;
using AutoMapper;
using DataManageSystem.Common;
using DataManageSystem.Data;
using DataManageSystem.Exceptions;
using DataManageSystem.Models;
using DataManageSystem.Models.LimsModels;
using DataManageSystem.Utils;
using Microsoft.EntityFrameworkCore;
using Microsoft.Win32;
using OfficeOpenXml;

namespace DataManageSystem.Services
{
    public class EquipmentServices
    {
        private readonly DeviceDbContext _context;
        private readonly ApplicationDbContext dbContext;
        private readonly IServiceScopeFactory _scopeFactory;
        private readonly UserServices userService;
        private readonly IHttpContextAccessor httpContextAccessor;
        private readonly IConfiguration _config;

        public EquipmentServices(
            DeviceDbContext context,
            ApplicationDbContext dbContext,
            IServiceScopeFactory scopeFactory,
            UserServices userServices,
            IHttpContextAccessor httpContextAccessor,
            IConfiguration _config
        )
        {
            this._context = context;
            this.dbContext = dbContext;
            this._scopeFactory = scopeFactory;
            this.userService = userServices;
            this.httpContextAccessor = httpContextAccessor;
            this._config = _config;
        }

        public Result SelectByPage(int page, int size, string? name)
        {
            var query = _context.TEquipments.Where(m => m.Valid == true).AsQueryable();

            if (!string.IsNullOrEmpty(name))
            {
                query = query.Where(m => m.Name.Contains(name));
            }
            int total = query.Count();
            var equipments = query.Skip((page - 1) * size).Take(size).ToList();
            foreach (var equipment in equipments)
            {
                var res = _context.TRegisters.FirstOrDefault(r => r.Code == equipment.Code);
                if (res != null)
                {
                    equipment.Protocol = res.Address3;
                }
                else
                {
                    equipment.Protocol = "其他";
                }
            }
            return Result.Success(equipments, total);
        }

        public void ImportDevicesByDateBase()
        {
            using (var scope = _scopeFactory.CreateScope())
            {
                //在服务类中注入 IServiceScopeFactory 来手动创建作用域，确保在异步任务中拥有独立的 DbContext：
                var context = scope.ServiceProvider.GetRequiredService<DeviceDbContext>();

                // 使用异步查询代替同步查询，避免阻塞主线程
                var equipments = context
                    .TEquipments.Where(e => e.Valid == true)
                    .Select(e => e.RegisterCode)
                    .ToList();

                // 过滤未迁移的设备
                var codes = _context
                    .TRegisters.Where(m => !equipments.Contains(m.Code))
                    .Select(m => m.Code);

                if (!codes.Any())
                {
                    throw new ServiceException("没有需要迁移的设备");
                }

                var currentTime = DateTime.Now;
                var equipmentList = new List<TEquipment>();

                // 避免重复调用 DateTime.Now，提前获取
                foreach (var code in codes)
                {
                    var equipment = new TEquipment
                    {
                        Guid = Guid.NewGuid().ToString(),
                        Name = code,
                        Code = code,
                        InstallationDate = currentTime,
                        LastMaintenanceTime = currentTime.AddMonths(-1),
                        NextMaintenanceTime = currentTime.AddMonths(6),
                        Type = "",
                        ProductionCompany = "",
                        AdditionalInfo = null, // json 字段
                        CreateTime = currentTime,
                        UpdateTime = currentTime,
                        CreateUser = "lkc",
                        UpdateUser = "lkc",
                        Valid = true,
                        DeptGuid = "",
                        Position = "",
                        SpaceGuid = "",
                        Status = 1,
                        AdministratorGuid = "",
                        BatchNumber = "",
                        OnlineStatusConfig = "",
                        MaintenanceCompanyGuid = "",
                        UseType = 0,
                        BeControlled = 1,
                        SystemClassification = "",
                        RegisterCode = code,
                        RegisterStateKey = "",
                        RegisterStateGuid = "",
                        Installer = "",
                        Supplier = "",
                        Purchaser = "",
                        PurchaseTime = currentTime,
                        //todo:兼容线上数据库 以下是南通医学项目特定的字段
                        //TestScope = "",
                        //Level = "",
                        //PrecisionStr = "",
                        //UseDept = "",
                        //UserName = "",
                        //DetectCycle = "",
                        //StorageLocation = "",
                    };

                    equipmentList.Add(equipment);
                }

                // 批量插入
                if (equipmentList.Any())
                {
                    try
                    {
                        context.TEquipments.AddRange(equipmentList);
                        context.SaveChanges();
                    }
                    catch (DbUpdateException dbEx)
                    {
                        throw new Exception(
                            "批量插入失败，具体原因：" + dbEx.InnerException.Message
                        );
                    }
                }
            }
        }

        public void ImportDataPoint(string registerCode)
        {
            // 先判断是否已导入
            var existingImport = dbContext.ImportRecords.FirstOrDefault(r =>
                r.DeviceName == registerCode
            );

            if (existingImport != null)
            {
                throw new ServiceException("请勿重复导入");
            }

            // 获取设备信息
            var register = _context.TEquipments.FirstOrDefault(e => e.RegisterCode == registerCode);

            if (register == null)
            {
                throw new ServiceException("没有相关记录在 t_equipment 表中！");
            }

            // 查询寄存器状态键
            var registerStateKeys = _context
                .TRegisterStateKeys.Where(r => r.RegisterCode == registerCode)
                .ToList();

            Console.WriteLine(registerStateKeys.Count);

            if (!registerStateKeys.Any())
            {
                throw new ServiceException("未找到对应的寄存器状态键，导入终止！");
            }

            // 构建需要导入的数据
            var dtoList = registerStateKeys
                .Select(registerStateKey => new TObjectAttribute
                {
                    Guid = Guid.NewGuid().ToString(),
                    ObjectGuid = register.Guid,
                    ShowTitle = registerStateKey.StateName,
                    RecordType = (int)registerStateKey.ReadType,
                    ValueType = registerStateKey.ValueType,
                    RegisterStateKey = registerStateKey.StateKey,
                    RegisterCode = registerStateKey.RegisterCode,
                    RegisterStateGuid = registerStateKey.Guid,
                    CreateTime = DateTime.Now,
                    UpdateTime = DateTime.Now,
                    CreateUser = "lkc",
                    UpdateUser = "lkc",
                    Valid = true,
                    Order = null,
                    Log = null,
                    LogRate = null,
                    Name = null,
                    WarningGuid = null,
                    RelatedAttributeGuid = null,
                    Type = null,
                    IsDefault = null,
                })
                .ToList();

            // 插入数据
            try
            {
                _context.TObjectAttributes.AddRange(dtoList);
                _context.SaveChanges();
            }
            catch (DbUpdateException dbEx)
            {
                throw new Exception("批量插入失败，具体原因：" + dbEx.InnerException?.Message);
            }
            catch (Exception ex)
            {
                throw new Exception("批量插入失败，具体原因：" + ex.Message);
            }

            // 获取当前用户
            var currentUser = TokenUtils.GetCurrentUser(httpContextAccessor, userService, _config);

            // 添加导入记录
            var importRecord = new ImportRecord
            {
                Id = 0,
                DeviceName = registerCode,
                ImportTime = DateTime.Now,
                Importer = currentUser?.Name ?? "lkc",
            };

            dbContext.ImportRecords.Add(importRecord);
            dbContext.SaveChanges();
        }

        public int GetDataCount()
        {
            int res = _context.TEquipments.Where(e => e.Valid == true).ToList().Count;
            return res;
        }

        public void OETableImport(string equipmentCode)
        {
            var currentTime = DateTime.Now;

            // 一次性查出设备和对应的属性（避免 N+1）
            var equipmentsWithAttrs = _context
                .TEquipments.Where(e => e.Name.Contains(equipmentCode))
                .Select(e => new
                {
                    EquipmentGuid = e.Guid,
                    Attributes = _context
                        .TObjectAttributes.Where(a =>
                            a.ObjectGuid == e.Guid && a.ShowTitle.Contains(equipmentCode)
                        )
                        .ToList(),
                })
                .ToList();

            // 生成新的设备集合
            var newEquipments = new List<TEquipment>();
            foreach (var eq in equipmentsWithAttrs)
            {
                foreach (var attr in eq.Attributes)
                {
                    var equ = new TEquipment
                    {
                        Guid = Guid.NewGuid().ToString(),
                        Name = attr.ShowTitle,
                        Code = "",
                        InstallationDate = currentTime,
                        LastMaintenanceTime = currentTime.AddMonths(-1),
                        NextMaintenanceTime = currentTime.AddMonths(6),
                        Type = "",
                        ProductionCompany = "",
                        AdditionalInfo = null,
                        CreateTime = currentTime,
                        UpdateTime = currentTime,
                        CreateUser = "lkc",
                        UpdateUser = "lkc",
                        Valid = true,
                        DeptGuid = "",
                        Position = "",
                        SpaceGuid = "",
                        Status = 1,
                        AdministratorGuid = "",
                        BatchNumber = "",
                        OnlineStatusConfig = "",
                        MaintenanceCompanyGuid = "",
                        UseType = 0,
                        BeControlled = 1,
                        SystemClassification = "",
                        RegisterCode = "",
                        RegisterStateKey = "",
                        RegisterStateGuid = "",
                        Installer = "",
                        Supplier = "",
                        Purchaser = "",
                        PurchaseTime = currentTime,
                    };

                    newEquipments.Add(equ);
                }
            }

            // 批量插入，减少数据库交互
            if (newEquipments.Any())
            {
                _context.TEquipments.AddRange(newEquipments);
                _context.SaveChanges();
            }
        }

        /// <summary>
        /// 映射关系同步
        /// </summary>
        public void OETableImport2(string equipmentCode)
        {
            // 一次性取出相关设备
            var equipmentsWithAttrs = _context
                .TEquipments.Where(e => e.Valid == true && e.Name.Contains(equipmentCode))
                .ToList();

            if (!equipmentsWithAttrs.Any())
                return;

            // 找到所有可能的名称集合
            var eqNames = equipmentsWithAttrs.Select(e => e.Name).ToList();

            // 一次性取出所有匹配的对象属性
            var attrs = _context
                .TObjectAttributes.Where(a => eqNames.Contains(a.ShowTitle))
                .ToList();

            foreach (var eq in equipmentsWithAttrs)
            {
                var attr = attrs.FirstOrDefault(a => a.ShowTitle == eq.Name);
                if (attr != null)
                {
                    attr.ObjectGuid = eq.Guid;
                }
            }
            // 统一保存，减少数据库交互
            _context.SaveChanges();
        }

        /// <summary>
        /// 配电箱设备同步
        /// </summary>
        /// <param name="equipmentCode"></param>
        public void OETableImport3(string equipmentCode)
        {
            var currentTime = DateTime.Now;

            var res = _context
                .TRegisterStateKeys.Where(a => a.StateName.Contains(equipmentCode))
                .ToList();
            var equipments = res.Select(attr => new TEquipment
                {
                    Guid = Guid.NewGuid().ToString(),
                    Name = attr.StateName,
                    Code = "",
                    InstallationDate = currentTime,
                    LastMaintenanceTime = currentTime.AddMonths(-1),
                    NextMaintenanceTime = currentTime.AddMonths(6),
                    Type = "",
                    ProductionCompany = "",
                    AdditionalInfo = null, // json 字段
                    CreateTime = currentTime,
                    UpdateTime = currentTime,
                    CreateUser = "lkc",
                    UpdateUser = "lkc",
                    Valid = true,
                    DeptGuid = "",
                    Position = "",
                    SpaceGuid = "",
                    Status = 1,
                    AdministratorGuid = "",
                    BatchNumber = "",
                    OnlineStatusConfig = "",
                    MaintenanceCompanyGuid = "",
                    UseType = 0,
                    BeControlled = 1,
                    SystemClassification = "",
                    RegisterCode = "",
                    RegisterStateKey = "",
                    RegisterStateGuid = "",
                    Installer = "",
                    Supplier = "",
                    Purchaser = "",
                    PurchaseTime = currentTime,
                })
                .ToList();

            _context.TEquipments.AddRange(equipments);
            _context.SaveChanges();
        }

        public void imortFromExcel(IFormFile file)
        {
            if (file == null || file.Length == 0)
                throw new ArgumentException("文件为空");

            using var stream = new MemoryStream();
            file.CopyToAsync(stream);
            stream.Position = 0;

            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            using var package = new ExcelPackage(stream);
            var worksheet = package.Workbook.Worksheets[0];
            int rowCount = worksheet.Dimension.Rows;

            var registers = new List<TRegister>();
            var stateKeys = new List<TRegisterStateKey>();

            for (int row = 2; row <= rowCount; row++) // 跳过表头
            {
                string seq = worksheet.Cells[row, 1].Text?.Trim();
                string monitor = worksheet.Cells[row, 2].Text?.Trim();

                if (string.IsNullOrEmpty(monitor))
                    continue;

                // ---------- 构造 register ----------
                var register = new TRegister
                {
                    Code = monitor + "明火报警",
                    Address1 = seq,
                    Address2 = "",
                    Address3 = "mediaWarn",
                    Address4 = "",
                    CreateTime = DateTime.Now,
                    CreateBy = "lkc",
                    UpdateTime = DateTime.Now,
                    IsDelete = 0,
                    UpdateBy = "lkc",
                    RegisterName = monitor + "明火报警",
                    Types = "",
                    ReadLength = 0,
                    TypeCode = "",
                    ModbusStation = 0,
                };
                registers.Add(register);

                var stateKey = new TRegisterStateKey
                {
                    Guid = Guid.NewGuid().ToString(),
                    RegisterCode = register.Code, // 关联 register 的 code
                    StateName = register.Code,
                    WriteState = "",
                    StateGuid = "",
                    ReadType = 2,
                    StateKey = register.Code,
                    IsLazy = "0",
                    IsInterval = "1",
                    ScanIntervalMs = 1000,
                    CreateTime = DateTime.Now,
                    CreateBy = "lkc",
                    UpdateTime = DateTime.Now,
                    UpdateBy = "lkc",
                    IsDelete = false,
                    ValueType = "字符串",
                    BitKey = 0,
                    KeyName = register.Code,
                    ValueRange = "",
                    InputType = "select",
                    TextFill = "${val}",
                    Formula = "",
                    InputFormula = "",
                    Composable = false,
                    IsMain = true,
                    Room = "",
                    DeviceName = "",
                    ShowOrder = "0",
                    WarningLevel = 0,
                    LogRate = "0",
                };
                stateKeys.Add(stateKey);
            }

            // ---------- 保存到数据库 ----------
            if (registers.Any())
            {
                _context.TRegisters.AddRange(registers);
                try
                {
                    _context.TRegisterStateKeys.AddRange(stateKeys);

                }catch (Exception ex)
                {
                    throw new Exception("批量插入失败，具体原因：" + ex.Message);
                }
                _context.SaveChanges();
            }
        }

        /// <summary>
        /// 配电箱点位同步
        /// </summary>
        /// <param name="equipmentCode"></param>
        public void OETableImport4(string equipmentCode)
        {
            // 查询寄存器状态键
            var registerStateKeys = _context
                .TRegisterStateKeys.Where(r => r.StateName.Contains(equipmentCode))
                .ToList();

            // 构建需要导入的数据
            var dtoList = registerStateKeys
                .Select(registerStateKey => new TObjectAttribute
                {
                    Guid = Guid.NewGuid().ToString(),
                    ObjectGuid = "",
                    ShowTitle = registerStateKey.StateName,
                    RecordType = (int)registerStateKey.ReadType,
                    ValueType = registerStateKey.ValueType,
                    RegisterStateKey = registerStateKey.StateKey,
                    RegisterCode = registerStateKey.RegisterCode,
                    RegisterStateGuid = registerStateKey.Guid,
                    CreateTime = DateTime.Now,
                    UpdateTime = DateTime.Now,
                    CreateUser = "lkc",
                    UpdateUser = "lkc",
                    Valid = true,
                    Order = null,
                    Log = null,
                    LogRate = null,
                    Name = null,
                    WarningGuid = null,
                    RelatedAttributeGuid = null,
                    Type = null,
                    IsDefault = null,
                })
                .ToList();

            // 插入数据
            try
            {
                _context.TObjectAttributes.AddRange(dtoList);
                _context.SaveChanges();
            }
            catch (DbUpdateException dbEx)
            {
                throw new Exception("批量插入失败，具体原因：" + dbEx.InnerException?.Message);
            }
            catch (Exception ex)
            {
                throw new Exception("批量插入失败，具体原因：" + ex.Message);
            }
        }
    }
}
